
/****
 * Copyright (C) 2006 dNux Team
 *                                                            ****
 * This program is free software; you can redistribute it and/or *
 * modify under the terms of the GNU General Public License as   *
 * published by the Free Software Foundation;                    *
 * either version 2 of the License.                              *
 *                                                               *
 * This program is distributed in the hope that it will be       *
 * useful, but WITHOUT ANY WARRANTY; without even the implied    *
 * warranty of without even the implied waranty of               *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.          *
 * See the GNU General Public License for more details.          *
 *                                                               *
 * You should have received a copy of the                        *
 * GNU General Public License                                    *
 * along with this program; if not, write to the                 *
 * Free Software Foundation, Inc.,                               *
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA. *
 *                                                               *
 ****                                                         ****/

#include "dpkg.h"

void
d_pkg_create_data_dir(TAR *a, char *from, char *directory, d_error_t **error)
{
  struct dirent *item = NULL;
  struct stat st;
  DIR *dir = NULL;
  char fullpath[2048];

  if (from) {
    dir = opendir(from);
    chdir(from);
  } else {
    dir = opendir(directory);
  }

  if (!dir) {
    d_error(LIBDPKG, "unable to open a directory");
    goto ret;
  }
  while((item = readdir(dir))) {
    if (! strcmp(item->d_name, ".") || ! strcmp(item->d_name, "..")) {
      continue;
    }

    if(from) {
	snprintf(fullpath, sizeof(fullpath), "%s", item->d_name);
    }
    else {
        snprintf(fullpath, sizeof(fullpath), "%s/%s", directory, item->d_name);
    }
    if (stat(fullpath, &st) == -1) {
      d_error(LIBDPKG, "stat error");
      continue;
    }
    
    tar_append_file(a, fullpath, fullpath);
    
    if ( S_ISDIR(st.st_mode) != 0) {
      d_pkg_create_data_dir(a, NULL, fullpath, error);
    }
  }
 ret:
  return;
}

void
d_pkg_create_data(char *from, d_error_t **error)
{
  pid_t pid;
  int status;

  int pipe_tar[2];
  int fd, len, err;
  unsigned int in, out;
  char buff[2048];

  FILE *file;
  TAR *tar;
  BZFILE *bzip2;

  if (pipe(pipe_tar) == -1) {
    d_error(LIBDPKG, "can't make pipe.");
    goto error;
  }

  pid = fork();
  if (pid == -1) {
    d_error(LIBDPKG, "can't fork.");
    goto error;
  }

  //son
  if (pid == 0) {
    close(pipe_tar[1]); //write
    fd = creat("data.tar.bz2", 0644);
    close(fd);
    file = fopen("data.tar.bz2", "w+");
    bzip2 = BZ2_bzWriteOpen(&err, file, 9, 0, 30);
    if (err != BZ_OK) goto bzip2_error;
    do {
      len = read(pipe_tar[0], buff, sizeof(buff));
      BZ2_bzWrite(&err, bzip2, buff, len);
      if (err != BZ_OK) goto bzip2_error;
    } while(len > 0);
    BZ2_bzWriteClose(&err, bzip2, 0, &in, &out);
  bzip2_error:
    close(pipe_tar[0]); //read
    exit(EXIT_SUCCESS);
  }
  //father
  else if (pid > 0) {
    close(pipe_tar[0]); //read
    
    if (tar_fdopen(&tar, pipe_tar[1], "data.tar", NULL, O_WRONLY, 0644, 0) == -1) {
      d_error(LIBDPKG, "tar_fdopen error.");
      goto tar_error;
    }

    d_pkg_create_data_dir(tar, from, NULL, error);    
    chdir("..");

    if (tar_close(tar) == -1) {
      d_error(LIBDPKG, "tar_close error.");
      goto tar_error;
    }
    waitpid(pid, &status, 0);
  tar_error:
    close(pipe_tar[1]); //write
  }

 error:
  return;
}

void
d_pkg_create_dnux(d_pkg_t *pkg, d_error_t **error)
{
  TAR *tar;
  int fd;
  fd = creat(pkg->file, 0644);
  if (tar_fdopen(&tar, fd, pkg->file, NULL, O_WRONLY, 0644, 0) == -1) {
    d_error(LIBDPKG, "tar_fdopen error");
    goto error;
  }
  if (tar_append_file(tar, "data.tar.bz2", "data.tar.bz2") == -1) {
    d_error(LIBDPKG, "tar_append_file error");
    goto error;
  }
  unlink("data.tar.bz2");

  if (tar_close(tar) == -1) {
    d_error(LIBDPKG, "tar_close error");
    goto error;
  }
  
 error:
  return;
}

void
d_pkg_create(d_pkg_t *pkg, char *from, d_error_t **error)
{
  //check args
  if (!pkg) goto error_args;
  if (!from) goto error_args;
  if (!error) goto error_args;
  if (!pkg->name) goto error_pkg;
  if (!pkg->version) goto error_pkg;
  if (!pkg->file) goto error_pkg;
  
  d_pkg_create_data(from, error);
  if (*error) goto error;
  
  d_pkg_create_dnux(pkg, error);
  if (*error) goto error;

  goto ok;
 error_pkg:
  d_error(LIBDPKG, "pkg invalid");
  goto ok;
 error_args:
  d_error(LIBDPKG, "arguments invalid");
  goto ok;
 error:
 ok:
  return ;

}
